#!/usr/bin/python
#
# Copyright 2009 Google Inc. All Rights Reserved.

"""Class to handle editing/deleting entries.

With this class we permit the user to edit, or delete and entry.
"""

__author__ = 'scottkirkwood@google.com (Scott Kirkwood)'

import datetime
import gviz_api
import logging
import os
import re
import schema
import sys
import time
import util

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

from django.utils import simplejson

import wsgiref.handlers

class WeightLog(webapp.RequestHandler):
  """Handling of the Weight Log."""

  @util.ForceLogin()
  def get(self):  # pylint: disable-msg=C6409
    """Standard GET request."""

    user = users.get_current_user()
    body = self.RecentInfo(user)
    self.response.out.write(body)

  def RecentInfo(self, user):
    today = datetime.date.today()
    last = schema.WeightEntry.gql('WHERE user=:1 ORDER BY date DESC', user).get()
    cur_date = None
    last_sld_cal = ''
    if last:
      day = datetime.timedelta(days=1)
      cur_date = last.date + day
      if cur_date > today:
        # We'll usually use the last entry + 1
        # It's often more correct than 'today' since it's in GMT time.
        cur_date = None
      last_weight = last.weight_kg
      if last.sld_calories:
        last_sld_cal = last.sld_calories;
      logging.debug('Got last weight %f and last date %s' % (last_weight, cur_date))
    else:
      logging.debug('Using default values')
      last_weight = 90
    if cur_date:
      cur_date_str = cur_date.isoformat()
    else:
      cur_date_str = ''
    path = os.path.join(os.path.dirname(__file__), 'index.html')
    template_values = {
        'user': user,
        'cur_date': cur_date_str,
        'last_weight': last_weight,
        'sld_cal': last_sld_cal,
    }
    return template.render(path, template_values)

class ListEntries(webapp.RequestHandler):
  """List all the entries for a user."""

  @util.ForceLogin()
  def get(self):  # pylint: disable-msg=C6409
    """Standard GET request."""

    user = users.get_current_user()
    body = self.ListEntries(user)
    self.response.out.write(body)

  def ListEntries(self, user):
    results = schema.WeightEntry.gql('WHERE user=:1 ORDER BY date DESC', user)
    list = []
    for entry in results:
      list.append({
        'date' : entry.date,
        'weight_kg': util.BlankForZero(entry.weight_kg),
        'workout_min': util.BlankForZero(entry.workout_min),
        'running_km': util.BlankForZero(entry.running_km),
        'sld_cal': util.BlankForZero(entry.sld_calories),
      })
    logging.debug('Got %d results' % len(list))
    path = os.path.join(os.path.dirname(__file__), 'entry_list.html')
    return template.render(path, dict(entries=list))

class ListChart(webapp.RequestHandler):
  """Handling of the Weight Log."""

  @util.ForceLogin()
  def get(self):  # pylint: disable-msg=C6409
    user = users.get_current_user()
    self.response.out.write(self.ListChartEntries(user))

  def ListChartEntries(self, user):
    results = schema.WeightEntry.gql('WHERE user=:1 ORDER BY date', user)
    data = []
    for entry in results:
      data.append({
        'date' : entry.date,
        'weight_kg': util.NullForZero(entry.weight_kg),
        'workout_min': util.NullForZero(entry.workout_min),
        'running_km': util.NullForZero(entry.running_km),
        'sld_cal': util.NullForZero(entry.sld_calories),
      })
    logging.debug('Got %d results' % len(data))
    description = {'date': ('date', 'Date'),
                   'weight_kg': ('number', 'Weight (Kg)'),
                   'workout_min': ('number', 'Workout (min)'),
                   'running_km': ('number', 'Running (Km)'),
                   'sld_cal': ('number', 'SLD (kcal)'),
                  }
    data_table = gviz_api.DataTable(description)
    data_table.LoadData(data)
    return data_table.ToJSonResponse(
        columns_order=('date',  # 0
                       'weight_kg',  # 1
                       'workout_min',  # 2
                       'running_km',  # 3
                       'sld_cal', # 4
                      ),
        order_by='date')


class AddLog(webapp.RequestHandler):
  """Add entry to Weight Log."""

  @util.ForceLogin()
  def post(self):
    """Standard POST request."""
    user = users.get_current_user()
    self.Add(user)

  def Add(self, user):
    """Add a new entry.

    Args:
      user: user to update.
    """
    date_input = self.request.get('date')
    weight_input = self.request.get('weight_kg')
    workout_min = self.request.get('workout_min')
    running_km = self.request.get('running_km')
    sld_cal = self.request.get('sld_cal')
    dttime = datetime.datetime.strptime(date_input, '%Y-%m-%d')
    date = datetime.date(dttime.year, dttime.month, dttime.day)

    prev = schema.WeightEntry.gql('WHERE user=:1 AND date=:2', user, date).get()
    if prev:
      log = prev
      had_prev = True
    else:
      log = schema.WeightEntry(user=user, date=date)
      had_prev = False

    try:
      log.weight_kg = SafeFloat(weight_input)
      log.workout_min = SafeFloat(workout_min)
      log.running_km = SafeFloat(running_km)
      log.sld_calories = SafeInt(sld_cal)
      log.is_iso = True
      log.put()
    except Exception, e:
      logging.error('Error adding: %s' % e)
      self.response.set_status(500)
      self.response.out.write(simplejson.dumps({
        'ok': False,
        'error': 'Unable to save: ' + str(e),
      }))
      return

    self.response.set_status(200)
    self.response.out.write(simplejson.dumps({
        'ok': True,
        'action': 'add',
        'date': date_input,
        'weight_kg': weight_input,
        'workout_min': workout_min,
        'running_km': running_km,
        'sld_cal': sld_cal,
        'overwrite': had_prev,
        }))


def main():
  application = webapp.WSGIApplication([
      ('/', WeightLog),
      ('/add', AddLog),
      ('/list', ListEntries),
      ('/chart/?.*$', ListChart),
      ])
  wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
  main()
